home *** CD-ROM | disk | FTP | other *** search
/ MIDICraft's MIDINET CD-ROM / MIDICraft's MIDINET CD-ROM.iso / DOSUTILS / MIDISORT / MTRACK.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-11  |  9.2 KB  |  384 lines

  1. #include "mtrack.hpp"
  2. #include <assert.h>
  3. #include <alloc.h>
  4. #include <string.h>
  5.  
  6. Trackinfo::Trackinfo()
  7. {
  8.   name_ = 0;
  9.   channel_ = NOCHANNEL;
  10.   for (int ch = 0; ch < 16; ch++)
  11.   {
  12.     program_[ch] = volume_[ch] = balance_[ch] = chorus_[ch] = reverb_[ch] = -1;
  13.     used_[ch] = 0;
  14.   }
  15. }
  16.  
  17. Trackinfo::~Trackinfo()
  18. {
  19.   settrackname(0);
  20. }
  21.  
  22. const char* Trackinfo::trackname()
  23. {
  24.   if (!name_)
  25.     return "";
  26.   else
  27.     return (const char*)name_;
  28. }
  29.  
  30. void Trackinfo::settrackname(char* name, int namelen)
  31. {
  32.   if (name_)
  33.   {
  34.     free(name_); name_ = 0;
  35.   }
  36.   if (namelen < 0)
  37.     namelen = strlen(name);
  38.   if (name && namelen > 0 && *name)
  39.   {
  40.     name_ = (char*)malloc(namelen+1);
  41.     assert(name_ != 0);
  42.     strncpy(name_, name, namelen);
  43.     name_[namelen] = '\0';
  44.   }
  45. }
  46.  
  47. MidiTrackinfo::MidiTrackinfo(char* name) : MidiRead(name)
  48. {
  49.   track_ = 0;
  50.   tempo_ = 0;
  51.   tactnom_ = tactdenom_ = 0;
  52.   if (getf())
  53.   {
  54.     run();
  55.     if (!tactnom_ || !tactdenom_)
  56.     {
  57.       tactnom_ = 4;
  58.       tactdenom_ = 4;
  59.     }
  60.     if (!tempo_)
  61.       tempo_ = 500000L;
  62.   }
  63. }
  64.  
  65. MidiTrackinfo::~MidiTrackinfo()
  66. {
  67.   for (int i = 0; i < tracks_; i++)
  68.     delete track_[i];
  69.   if (track_)
  70.   {
  71.     free(track_); track_ = 0;
  72.   }
  73. }
  74.  
  75. void MidiTrackinfo::head(unsigned version, unsigned tracks, unsigned unitsperbeat)
  76. {
  77.   if (tracks > 0)
  78.   {
  79.     track_ = (Trackinfo**) malloc(sizeof(Trackinfo*) * tracks);
  80.     if (!track_)
  81.     {
  82.       error("out of memory");
  83.       tracks_ = 0;
  84.     }
  85.     for (int i = 0; i < tracks_; i++)
  86.       track_[i] = 0;
  87.   }
  88. }
  89.  
  90. void MidiTrackinfo::track(int trackno, long length, int channel)
  91. {
  92.   track_[trackno_-1] = new Trackinfo;
  93.   if (!track_[trackno-1])
  94.   {
  95.     error("out of memory");
  96.     return;
  97.   }
  98.   track_[trackno_-1]->pos_ = getpos();
  99.   track_[trackno_-1]->len_ = length;
  100.   track_[trackno_-1]->channel_ = channel;
  101.  
  102.   if (channel >= 0 && channel < 16)
  103.     track_[trackno_-1]->used_[channel] = 1;
  104. }
  105.  
  106. void MidiTrackinfo::endtrack(int trackno)
  107. {
  108. }
  109.  
  110. void MidiTrackinfo::text(int what, int len, char* whattext, unsigned char* txt)
  111. {
  112.   if (what == meta_trackname && track_[trackno_-1] && strlen(track_[trackno_-1]->trackname()) == 0)
  113.     track_[trackno_-1]->settrackname(txt, len);
  114. }
  115.  
  116. void MidiTrackinfo::end()
  117. {
  118. }
  119.  
  120.  
  121. void MidiTrackinfo::tact(int nom, int denom, int unitsperbeat, int notes32perbeat)
  122. {
  123.   tactnom_ = nom;
  124.   tactdenom_ = denom;
  125. }
  126.  
  127. void MidiTrackinfo::tempo(unsigned long ticks)
  128. {
  129.   tempo_ = ticks;
  130. }
  131.  
  132. void MidiTrackinfo::key(int signature, int isminor)
  133. {
  134. }
  135.  
  136. void MidiTrackinfo::noteon(int channel, int note, int vel)
  137. {
  138.   if (track_ && track_[trackno_-1])
  139.     track_[trackno_-1]->used_[channel] = 1;
  140. }
  141.  
  142. void MidiTrackinfo::noteoff(int channel, int note, int vel)
  143. {
  144.   if (track_ && track_[trackno_-1])
  145.     track_[trackno_-1]->used_[channel] = 1;
  146. }
  147.  
  148. void MidiTrackinfo::program(int channel, int prg)
  149. {
  150.   if (track_ && track_[trackno_-1])
  151.   {
  152.     if (track_[trackno_-1]->program_[channel] < 0)
  153.       track_[trackno_-1]->program_[channel] = prg;
  154.     track_[trackno_-1]->used_[channel] = 1;
  155.   }
  156. }
  157.  
  158. void MidiTrackinfo::balance(int channel, int val)
  159. {
  160.   if (track_ && track_[trackno_-1])
  161.   {
  162.     if (track_[trackno_-1]->balance_[channel] < 0)
  163.       track_[trackno_-1]->balance_[channel] = val;
  164.     track_[trackno_-1]->used_[channel] = 1;
  165.   }
  166. }
  167.  
  168. void MidiTrackinfo::volume(int channel, int val)
  169. {
  170.   if (track_ && track_[trackno_-1])
  171.   {
  172.     if (track_[trackno_-1]->volume_[channel] < 0)
  173.       track_[trackno_-1]->volume_[channel] = val;
  174.     track_[trackno_-1]->used_[channel] = 1;
  175.   }
  176. }
  177.  
  178. void MidiTrackinfo::reverb(int channel, int val)
  179. {
  180.   if (track_ && track_[trackno_-1])
  181.   {
  182.     if (track_[trackno_-1]->reverb_[channel] < 0)
  183.       track_[trackno_-1]->reverb_[channel] = val;
  184.     track_[trackno_-1]->used_[channel] = 1;
  185.   }
  186. }
  187.  
  188. void MidiTrackinfo::chorus(int channel, int val)
  189. {
  190.   if (track_ && track_[trackno_-1])
  191.   {
  192.     if (track_[trackno_-1]->chorus_[channel] < 0)
  193.       track_[trackno_-1]->chorus_[channel] = val;
  194.     track_[trackno_-1]->used_[channel] = 1;
  195.   }
  196. }
  197.  
  198. void MidiTrackinfo::endmidi()
  199. {
  200. }
  201.  
  202. void MidiTrackinfo::error(const char* msg)
  203. {
  204.   printf("error: %s\n", msg);
  205. }
  206.  
  207. const char* channelstr(int channel)
  208. {
  209.   if (channel == MULTICHANNEL)
  210.     return "MULTICHANNEL";
  211.   else if (channel == NOCHANNEL)
  212.     return "NOCHANNEL";
  213.   else if (channel >= 0 && channel <= 15)
  214.   {
  215.   static char chnum[3];
  216.  
  217.     sprintf(chnum, "%d", channel+1);
  218.     return (const char*)chnum;
  219.   }
  220.   assert((channel >= 0 && channel <= 15) || channel == MULTICHANNEL || channel == NOCHANNEL);
  221.   return 0;
  222. }
  223.  
  224. void MidiTrackinfo::printchannelparams(int trackno, int channel, FILE* output, int verbose)
  225. {
  226. Trackinfo* info = trackinfo(trackno);
  227.  
  228.   if (channel >= 0 && !info->used_[channel])
  229.     return;
  230.  
  231.   if (!output)
  232.     output = stdout;
  233.   if (verbose)
  234.   {
  235.      if (channel == 9)
  236.        fprintf(output, "  program: Drums\n");
  237.      else if (info->program_[channel] >= 0)
  238.        fprintf(output, "  program: %s\n", progname(info->program_[channel], channel));
  239.      else if (channel != NOCHANNEL)
  240.      {
  241.        fprintf(output, "  program: ");
  242.        if (channel < gm_drumchannel)
  243.      fprintf(output, "default:%s", progname(0, channel));
  244.        else
  245.      fprintf(output, "default:%s or Drums?", progname(0, channel));
  246.      }
  247.      if (info->volume_[channel] >= 0)
  248.        fprintf(output, "  volume: %d  (0=mute,127=full)\n", info->volume_[channel]);
  249.      if (info->balance_[channel] >= 0)
  250.        fprintf(output, "  balance: %d (0=left, 64=mid, 127=right)\n", info->balance_[channel]);
  251.      if (info->chorus_[channel] >= 0)
  252.        fprintf(output, "  chorus: %d (0-127)\n", info->chorus_[channel]);
  253.      if (info->reverb_[channel] >= 0)
  254.        fprintf(output, "  reverb: %d (0-127)\n", info->reverb_[channel]);
  255.   }
  256.   else
  257.   {
  258.     if (channel == 9)
  259.       fprintf(output, "(Drums)");
  260.     else if (info->program_[channel] >= 0)
  261.       fprintf(output, "(%s)", progname(info->program_[channel], channel));
  262.     else if (channel != NOCHANNEL)
  263.     {
  264.       if (channel < gm_drumchannel)
  265.     fprintf(output, "(default:%s)", progname(0, channel));
  266.       else
  267.     fprintf(output, "(default:%s or Drums?)", progname(0, channel));
  268.     }
  269.   }
  270. }
  271.  
  272. void MidiTrackinfo::print(int trackno, FILE* output, int verbose)
  273. {
  274. Trackinfo* info = trackinfo(trackno);
  275.  
  276.   if (!info)
  277.     return;
  278.  
  279.   if (!output)
  280.     output = stdout;
  281.   fprintf(output, "Track %d", trackno);
  282.   if (verbose)
  283.   {
  284.     fprintf(output, ":\n");
  285.     fprintf(output, "  channel: %s\n", channelstr(info->channel_));
  286.     if (strlen(info->trackname()) > 0)
  287.       fprintf(output, "  name: \"%s\"\n", info->trackname());
  288.     else if (trackno == 1 && version_ == 1)
  289.       fprintf(output, "  tempo track\n");
  290.  
  291.     if (info->channel_ == MULTICHANNEL)
  292.     {
  293.       for (int ch = 0; ch < 16; ch++)
  294.       if (info->used_[ch])
  295.       {
  296.     fprintf(output, "channel %s\n", channelstr(ch));
  297.     printchannelparams(trackno, ch, output, verbose);
  298.       }
  299.     }
  300.     else
  301.     {
  302.        printchannelparams(trackno, info->channel_, output, verbose);
  303.     }
  304.   }
  305.   else
  306.   {
  307.     if (info->channel_ == MULTICHANNEL)
  308.     {
  309.       fprintf(output, ": %s\n", channelstr(info->channel_));
  310.       for (int ch = 0; ch < 16; ch++)
  311.       if (info->used_[ch])
  312.       {
  313.     fprintf(output, " [%s]: ", channelstr(ch));
  314.     printchannelparams(trackno, ch, output, verbose);
  315.     fprintf(output, "\n");
  316.       }
  317.     }
  318.     else
  319.     {
  320.       fprintf(output, " [%s]: ", channelstr(info->channel_));
  321.       if (version_ == 1 && trackno == 1 && strlen(info->trackname()) == 0)
  322.     fprintf(output, "tempo track ");
  323.       else
  324.     fprintf(output, "\"%s\" ",  info->trackname());
  325.  
  326.       printchannelparams(trackno, info->channel_, output, verbose);
  327.       fprintf(output, "\n");
  328.     }
  329.   }
  330. }
  331.  
  332. void MidiTrackinfo::print(FILE* output, int verbose)
  333. {
  334.   if (!getf() || !tracks_)
  335.     return;
  336.   if (!output)
  337.     output = stdout;
  338.  
  339.   if (verbose)
  340.   {
  341.     printf("Midi format %d ", version_);
  342.     switch(version_)
  343.     {
  344.     case 0: printf("(single multichannel track)\n"); break;
  345.     case 1: printf("(tempo track and channel separated tracks)\n"); break;
  346.     case 2: printf("(each track is a song)\n"); break;
  347.     default: printf("(unknown)\n"); break;
  348.     }
  349.     if (tempo_ != 0)
  350.     {
  351. #ifdef USE_FLOAT
  352.       fprintf(output, "Tempo: %2.2f beats/min\n", (float)(60000000.0 / (float)tempo_));
  353. #else
  354.       int beats_div = (int)(60000000L / tempo_);
  355.       long beats_mod = 60000000L % tempo_;
  356.       int beats_frac = (int)((beats_mod * 100) / tempo_);
  357.       fprintf(output, "Tempo: %2d.%02d beats/min\n", beats_div, beats_frac);
  358. #endif
  359.     }
  360.     if (tactnom_ != 0 && tactdenom_ != 0)
  361.       fprintf(output, "Tact: %d/%d\n", tactnom_, tactdenom_);
  362.     if (unitsperbeat_)
  363.       fprintf(output, "Resolution: 1/%d\n", unitsperbeat_ * 4);
  364.   }
  365.  
  366.   for (int i = 1; i <= trackcount(); i++)
  367.     print(i, output, verbose);
  368. }
  369.  
  370. Trackinfo* MidiTrackinfo::trackinfo(int trackno)
  371. {
  372.   if (trackno >= 1 && trackno <= trackcount())
  373.     return track_[trackno-1];
  374.   return 0;
  375. }
  376.  
  377. void MidiTrackinfo::control(int channel, int what, int value)
  378. {
  379.   if (track_ && track_[trackno_-1])
  380.   {
  381.     track_[trackno_-1]->used_[channel] = 1;
  382.   }
  383. }
  384.